package club.bigtian.sync.controller;

import club.bigtian.sync.config.SyncConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 配置API控制器
 * 提供配置的REST API接口
 */
@RestController
@RequestMapping("/api")
public class RestConfigController {

    private static final Logger logger = LoggerFactory.getLogger(RestConfigController.class);

    @Autowired
    private SyncConfig syncConfig;

    @Autowired
    private Environment env;

    @Autowired
    private ResourceLoader resourceLoader;

    /**
     * 获取当前配置
     * GET /api/config
     * @return 配置信息
     */
    @GetMapping("/config")
    public ResponseEntity<?> getConfig() {
        Map<String, Object> response = new HashMap<>();

        try {
            // 直接返回SyncConfig对象
            response.put("success", true);
            response.put("config", syncConfig);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("获取配置失败", e);
            response.put("success", false);
            response.put("message", "获取配置失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }
    
    /**
     * 获取上次binlog同步位置
     * GET /api/binlog/position
     * @return 上次同步位置信息
     */
    @GetMapping("/binlog/position")
    public ResponseEntity<?> getBinlogPosition() {
        Map<String, Object> response = new HashMap<>();
        
        try {
            response.put("success", true);
            response.put("filename", syncConfig.getLastBinlogFilename());
            response.put("position", syncConfig.getLastBinlogPosition());
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("获取binlog位置失败", e);
            response.put("success", false);
            response.put("message", "获取binlog位置失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * 更新配置
     * POST /api/config
     * @param requestBody 请求体
     * @return 更新结果
     */
    @PostMapping("/config")
    public ResponseEntity<?> updateConfig(@RequestBody SyncConfig requestSyncConfig) {
        Map<String, Object> response = new HashMap<>();

        try {

            // 更新内存中的配置
            updateSyncConfig(requestSyncConfig);

            // 更新配置文件
            updateConfigFile(requestSyncConfig);

            response.put("success", true);
            response.put("message", "配置已成功更新");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("更新配置失败", e);
            response.put("success", false);
            response.put("message", "更新配置失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }

    /**
     * 更新SyncConfig对象
     * @param requestSyncConfig 配置
     */
    private void updateSyncConfig(SyncConfig requestSyncConfig) {
        int diskFlushInterval = syncConfig.getDiskFlushInterval();
        syncConfig = requestSyncConfig;
        if (diskFlushInterval == syncConfig.getDiskFlushInterval()) {
            return;
        }
        // 更新磁盘刷新间隔
        syncConfig.updateDiskFlushInterval();
    }

    /**
     * 更新配置文件
     * @param requestSyncConfig 配置
     * @throws IOException IO异常
     */
    private void updateConfigFile( SyncConfig requestSyncConfig) throws IOException {
        Properties properties = new Properties();
        Path configPath = Paths.get("config/application.properties");
        
        // 先加载现有配置
        try (InputStream is = Files.newInputStream(configPath)) {
            properties.load(is);
        } catch (IOException e) {
            logger.warn("无法加载现有配置文件，将创建新配置文件", e);
        }

       // 通过反射获取所有字段的@Value注解并更新配置
       Field[] fields = SyncConfig.class.getDeclaredFields();
       for (Field field : fields) {
           field.setAccessible(true);
           Value valueAnnotation = field.getAnnotation(Value.class);
           if (valueAnnotation != null) {
               String key = valueAnnotation.value().replace("${", "").replace("}", "").split(":")[0];
               try {
                   Object value = field.get(requestSyncConfig);
                   if (value != null) {
                       properties.setProperty(key, String.valueOf(value));
                   }
               } catch (IllegalAccessException e) {
                   logger.error("更新配置项{}失败", key, e);
               }
           }
       }
        // 保存配置
        try (OutputStream os = Files.newOutputStream(configPath)) {
            properties.store(os, "Updated by ClickHouse-MySQL Sync Tool");
        }
    }
    
    /**
     * 更新上次同步的binlog位置
     * POST /api/binlog/position
     * @param requestBody 请求体
     * @return 更新结果
     */
    @PostMapping("/binlog/position")
    public ResponseEntity<?> updateBinlogPosition(@RequestBody Map<String, Object> requestBody) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            String filename = (String) requestBody.get("filename");
            Long position = Long.parseLong(requestBody.get("position").toString());
            
            if (filename == null || position == null) {
                response.put("success", false);
                response.put("message", "请求体中缺少必要的参数");
                return ResponseEntity.ok(response);
            }
            
            // 更新内存中的配置
            syncConfig.setLastBinlogFilename(filename);
            syncConfig.setLastBinlogPosition(position);
            
            // 更新配置文件
            Properties properties = new Properties();
            Path configPath = Paths.get("config/application.properties");
            
            // 先加载现有配置
            try (InputStream is = Files.newInputStream(configPath)) {
                properties.load(is);
            } catch (IOException e) {
                logger.warn("无法加载现有配置文件，将创建新配置文件", e);
            }
            
            // 更新配置项
            properties.setProperty("sync.binlog.last.filename", filename);
            properties.setProperty("sync.binlog.last.position", position.toString());
            
            // 保存配置
            try (OutputStream os = Files.newOutputStream(configPath)) {
                properties.store(os, "Updated by ClickHouse-MySQL Sync Tool");
            }
            
            response.put("success", true);
            response.put("message", "Binlog位置已成功更新");
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            logger.error("更新Binlog位置失败", e);
            response.put("success", false);
            response.put("message", "更新Binlog位置失败: " + e.getMessage());
            return ResponseEntity.ok(response);
        }
    }
} 